<?php
/**
\cond
ooooo                        
`888'                        
 888  oo.ooooo.  oooo    ooo 
 888   888' `88b  `88.  .8'  
 888   888   888   `88..8'   
 888   888   888    `888'    
o888o  888bod8P'     .8'     
       888       .o..P'      
      o888o      `Y8P'       
\endcond

\file maat.php
\brief	Librairie Maat servant à gérer le reroutage et la réecriture d'URL.
\author 	: 	Loïc Coenen
\date 		:	06/09/2011

Voir \ref maat


\page maat Réecriture d'URL et routage

Lors de la création d'un site web, il importe d'organiser dés le début les différents scripts PHP et leur emplacement. 
Grâce au module Maat, vous pouvez trés facilement définir une redirection d'URL à l'aide du module mod_rewrite d'Apache. 
Le module Maat permet aux différents modules de gérer une redirection d'URL à l'aide d'un simple code PHP. Voici un exemple simple :

\code
include("lib/ipy/ipy.php");

$maat =  new maat();
$maat -> route('home', function ($arg){ 
        echo 'Hello World!';	});
$maat -> index();
\endcode 

Le code précédent doit se trouver dans le fichier \b index.php situé à la racine de votre espace Web. La fonction maat::route() permet d'indiquer au systéme que la fonction callback doit être appelée lorsque l'URL home est appelée.

La redirection d'URL permet la transmission d'argument au travers de l'URL, sans forcément passer par une chaine de requête et un passage par le tableau $_GET. 
Pour çela, il suffit d'indiquer un paramétre précédé par le signe dollar ($), et de le séparer d'autres arguments à l'aide d'un tiret tiret (-). 
Les arguments sont passés à la fonction $callback en tant que premier paramétre.
\code
$maat -> route('news-$number', function ($arg){ 
        echo 'News' . $arg['number'];	});
\endcode		
Le nombre d'argument est illimité, mais doivent être distingués par le signe "tiret" (-). On peut dés lors trés bien imaginer une construction du type :
\code
$maat -> route('news-$number-delete', function ($arg){ 
        echo 'Suppression de la news numéro ' . $arg['number'];	});
\endcode

Enfin, la méthode route permet d'inclure des fichiers qui seront interpreté par le gestionnaire de template (\ref Smarty). Dans ce cas, il faut utiliser la fonction maat::link.

\remark Au cas où il faudrait reconfiguer l'URL rewriting,
	il faut créer un fichier .htaccess indiquant les commandes suivantes
	\code
DirectoryIndex index.php
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule (.*) /ipy/index.php?q=$1 [L,QSA]
\endcode
Attention à ne pas oublier de remplacer \em ipy par l'URL de l'index.	

**/

/**

\brief Classe principale de la libraire maat

Voir \ref maat
**/
class maat {

	public $tpl;
	private $route_table;

	/**
		\brief Constructeur
		\param $tpl Une instance du gestionnaire de template \b Smarty
	**/
	function __construct(Smarty $tpl){
	
		$this->tpl = $tpl;
		$this->route_table 	= array();
		
	}

	/**
		Lance le routage de la page
	*/
	public function index()	{

		if(!array_key_exists('q', $_GET)){								//	On demande l'index
			$args	= array();
		}	
		else {
			$args = preg_split('(-|/)', $_GET['q']);
		}

		$found = false;
		
		foreach ($this->route_table as $route){
			$correct_route	=	true;
			$cb_args	=	array();
			if(count($route['args'])	==	count($args)){
				for($i = 0; $i < count($route['args']); $i++){
					if(substr_count($route['args'][$i], '$')){						//	Argument
						$cb_arg_name = str_replace('$', '', $route['args'][$i]);
						$cb_args[$cb_arg_name]	=	$args[$i];
					}
					else {
						if($route['args'][$i]	!=	$args[$i]){
							$correct_route	=	false;	break;
						}
					}
				}
				if($correct_route){
					
					if($route['type'] == 'cb'){
						call_user_func($route['cb'], $cb_args, $this->tpl);
					}
					else if($route['type'] == 'template'){
						$this->tpl->assign($cb_args);
						$this->tpl->display($route['cb']);
					}
					$found = true;
				}
			}
		}
		if(!$found){
                    $this->tpl->assign('page', $_GET['q']);
                    $this->tpl->display('templates/not_found.tpl');
		}
	}
	
	/**
	 *	\brief	Lie une route a un template
	 * @param type $route	Liste d'argument permettant d'accéder à la page.
	 *	Voir la fonction route()
	 * @param type $template URL du template à charger
	 * 
	 * Note : les variables présente dans $route seront assignée directement
	 * dans Smarty
	 */
	function link($arguments, $template){
		
		$arguments = $arguments == '' ? array(): $arguments;
		if(!is_array($arguments)){	$arguments	=	preg_split('(-|/)', $arguments);	}
		
		$this->route_table[]	=	array('args' 	=> 	$arguments, 
			'type'	=>	'template',	
			'cb'	=>	$template);
		
		
	}	
	
	/**
		\brief Ajoute une route à la table
		
		\param $argument Liste d'argument à reconnaitre lors de l'appel
		\param $callback Paire objet-méthode, méthode personalisée ou fichier à inclure
		
		La fonction route() fonctionne comme suit: chaque page est réorientée depuis une adresse
		"propre", séparée par des tirets (\em "delete-news-22") vers une fonction spécifique.
		
		La fonction peut-être basée sur des arguments - ainsi, router \em "delete-news-$n" permettra à la fonction
		callback de reçevoir l'argument "n" au sein d'un array.
		
		L'argument \em $callback peut-être
		1. Une réference de fonction ou une fonction anonyme
		2. Un nom de fonction dans l'espace global
		3. Une paire objet-méthode ou classe-méthode
		4. Un fichier à inclure. Dans ce cas, il s'agit d'une chaine de caractére commençant par le signe
		"deux points"
		
		L'argument de la fonction \em $callback sera la liste d'argument effectivement appelée.
		
	**/
	public function route($arguments, $callback){
	
		$arguments = $arguments == '' ? array(): $arguments;
		if(!is_array($arguments)){	$arguments	=	preg_split('(-|/)', $arguments);	}
		
		$this->route_table[]	=	array('args' 	=> 	$arguments, 
			'type'	=>	'cb',	
			'cb'	=>	$callback);
	
	}

};
?>
